// FanczosIpl.h
// 创建者：于玉龙
//
// Fanczos Interpolation（Fanczos 软件插值）
// 功能说明：
//
// 修订历史：
// 2012年12月12日（于玉龙）
//     初始版本，从 AffineTrans.cu 文件中分离出来。
//     修改了输入参数 inimg 的传递形式为按引用传递。

#ifndef __FANCZOSIPL_H__
#define __FANCZOSIPL_H__

#include "Image.h"

// Device 子程序：_fanczosInterpoDev（Fanczos 插值）
// Fanczos 软件插值算法，根据给定的图像和指定的坐标，返回该坐标的插值值。注意，
// 为了加快程序的执行速度，这个函数并不是十分健壮，函数中，没有对 inimg 的数据
// 合法性进行检查，所以调用该子程序一定要保证数据的合法性，否则会导致不可预知的
// 结果。
static __device__ unsigned char  // 返回值：插值值
_fanczosInterpoDev(
        const ImageCuda &inimg,  // 输入图像，希望 CUDA 足够聪明，这种按值传递
                                 // 参数的方法由于其 inline 的调用模式，不会带
                                 // 来性能的损失。
        float x, float y         // 读取数据的坐标
);

// Device 全局常量：_fanczosCoeffDev（Fanczos 插值系数）
// 用于进行 Fanczos 软件插值的系数表。
static __device__ const float _fanczosCoeffDev[10][10][16] = {
    { // [0]
        // [0][0]
        {  0.000000,  0.000000,  0.000000,  0.000000,  0.000000,  1.000000,
           0.000000,  0.000000,  0.000000,  0.000000,  0.000000,  0.000000,
           0.000000,  0.000000,  0.000000,  0.000000 },
        // [0][1]
        { -0.245915, -0.007606, -0.265837,  0.036235, -0.130966,  1.869223,
           0.175148, -0.040077, -0.245915, -0.007606, -0.265837,  0.036235,
           0.046293,  0.000848,  0.041959,  0.003820 },
        // [0][2]
        { -0.220745, -0.030128, -0.259005,  0.018282, -0.220755,  1.801697,
           0.396702, -0.091830, -0.220745, -0.030128, -0.259005,  0.018282,
           0.046299,  0.003405,  0.038003,  0.009671 },
        // [0][3]
        { -0.183163, -0.065196, -0.235574, -0.010222, -0.266985,  1.653084,
           0.651196, -0.149528, -0.183163, -0.065196, -0.235574, -0.010222,
           0.043693,  0.007535,  0.032411,  0.016902 },
        // [0][4]
        { -0.138411, -0.108582, -0.199271, -0.047797, -0.273987,  1.442786,
           0.922267, -0.205346, -0.138411, -0.108582, -0.199271, -0.047797,
           0.038828,  0.012944,  0.025923,  0.024709 },
        // [0][5]
        { -0.091757, -0.155112, -0.155112, -0.091757, -0.250136,  1.192366,
           1.192366, -0.250136, -0.091757, -0.155112, -0.155112, -0.091757,
           0.032272,  0.019236,  0.019236,  0.032272 },
        // [0][6]
        { -0.047797, -0.199271, -0.108582, -0.138411, -0.205346,  0.922267,
           1.442786, -0.273987, -0.047797, -0.199271, -0.108582, -0.138411,
           0.024709,  0.025923,  0.012944,  0.038828 },
        // [0][7]
        { -0.010222, -0.235574, -0.065196, -0.183163, -0.149528,  0.651196,
           1.653085, -0.266985, -0.010222, -0.235574, -0.065196, -0.183163,
           0.016902,  0.032411,  0.007535,  0.043693 },
        // [0][8]
        {  0.018282, -0.259005, -0.030128, -0.220745, -0.091830,  0.396702,
           1.801697, -0.220755,  0.018282, -0.259005, -0.030128, -0.220745,
           0.009671,  0.038003,  0.003405,  0.046299 },
        // [0][9]
        {  0.036235, -0.265837, -0.007606, -0.245915, -0.040077,  0.175148,
           1.869223, -0.130966,  0.036235, -0.265837, -0.007606, -0.245915,
           0.003820,  0.041959,  0.000848,  0.046293 }
    }, { // [1]
        // [1][0]
        { -0.245915, -0.130966, -0.245915,  0.046293, -0.007606,  1.869223,
          -0.007606,  0.000848, -0.265837,  0.175148, -0.265837,  0.041959,
           0.036235, -0.040077,  0.036235,  0.003820 },
        // [1][1]
        { -0.226157, -0.140049, -0.270076,  0.043489, -0.140049,  1.891722,
           0.169479, -0.040090, -0.270076,  0.169479, -0.259318,  0.029049,
           0.043489, -0.040090,  0.029049,  0.010148 },
        // [1][2]
        { -0.193387, -0.157168, -0.279742,  0.031101, -0.229975,  1.819735,
           0.393373, -0.092974, -0.253452,  0.139746, -0.229975,  0.004358,
           0.047837, -0.037101,  0.019491,  0.018133 },
        // [1][3]
        { -0.151962, -0.180783, -0.275321,  0.008558, -0.275321,  1.666033,
           0.650286, -0.151962, -0.219852,  0.089594, -0.180783, -0.031369,
           0.048915, -0.031369,  0.008558,  0.026777 },
        // [1][4]
        { -0.106894, -0.208111, -0.259376, -0.023361, -0.280902,  1.451089,
           0.923877, -0.209184, -0.175061,  0.025207, -0.117273, -0.075754,
           0.046823, -0.023361, -0.002760,  0.035041 },
        // [1][5]
        { -0.062781, -0.235621, -0.235621, -0.062781, -0.255485,  1.196923,
           1.196923, -0.255485, -0.125189, -0.046205, -0.046205, -0.125189,
           0.041987, -0.013627, -0.013627,  0.041987 },
        // [1][6]
        { -0.023361, -0.259376, -0.208111, -0.106894, -0.209184,  0.923877,
           1.451089, -0.280902, -0.075754, -0.117272,  0.025207, -0.175061,
           0.035041, -0.002760, -0.023361,  0.046823},
        // [1][7]
        {  0.008558, -0.275321, -0.180783, -0.151962, -0.151962,  0.650285,
           1.666033, -0.275321, -0.031369, -0.180783,  0.089595, -0.219852,
           0.026777,  0.008558, -0.031369,  0.048915 },
        // [1][8]
        {  0.031101, -0.279742, -0.157168, -0.193387, -0.092974,  0.393373,
           1.819735, -0.229975,  0.004358, -0.229975,  0.139746, -0.253452,
           0.018133,  0.019491, -0.037101,  0.047837 },
        // [1][9]
        {  0.043489, -0.270076, -0.140049, -0.226157, -0.040090,  0.169479,
           1.891722, -0.140049,  0.029049, -0.259318,  0.169479, -0.270076,
           0.010148,  0.029049, -0.040090,  0.043489 }
    }, { // [2]
        // [2][0]
        { -0.220745, -0.220755, -0.220745,  0.046299, -0.030128,  1.801697,
          -0.030128,  0.003405, -0.259005,  0.396702, -0.259005,  0.038003,
           0.018282, -0.091830,  0.018282,  0.009671 },
        // [2][1]
        { -0.193387, -0.229975, -0.253452,  0.047837, -0.157168,  1.819735,
           0.139746, -0.037101, -0.279742,  0.393373, -0.229975,  0.019491,
           0.031101, -0.092974,  0.004358,  0.018133 },
        // [2][2]
        { -0.156579, -0.241512, -0.275172,  0.041121, -0.241512,  1.745519,
           0.355495, -0.089783, -0.275172,  0.355495, -0.173507, -0.011604,
           0.041121, -0.089783, -0.011604,  0.027480 },
        // [2][3]
        { -0.114726, -0.254647, -0.285522,  0.025124, -0.281773,  1.592521,
           0.603626, -0.148955, -0.248865,  0.288363, -0.094397, -0.053683,
           0.047468, -0.082679, -0.028258,  0.036405 },
        // [2][4]
        { -0.072318, -0.267914, -0.286025, -0.000000, -0.283278,  1.381309,
           0.868400, -0.206984, -0.206984,  0.200462,  0.000000, -0.103448,
           0.049850, -0.072318, -0.044463,  0.043712 },
        // [2][5]
        { -0.033132, -0.279226, -0.279226, -0.033132, -0.255000,  1.133429,
           1.133429, -0.255000, -0.156383,  0.101247,  0.101247, -0.156383,
           0.048436, -0.059371, -0.059371,  0.048436 },
        // [2][6]
        { -0.000000, -0.286025, -0.267914, -0.072318, -0.206984,  0.868400,
           1.381309, -0.283278, -0.103448,  0.000000,  0.200462, -0.206984,
           0.043712, -0.044463, -0.072318,  0.049850 },
        // [2][7]
        {  0.025124, -0.285522, -0.254647, -0.114726, -0.148955,  0.603625,
           1.592521, -0.281773, -0.053683, -0.094397,  0.288363, -0.248865,
           0.036405, -0.028258, -0.082679,  0.047468 },
        // [2][8]
        {  0.041121, -0.275172, -0.241512, -0.156579, -0.089783,  0.355494,
           1.745518, -0.241512, -0.011604, -0.173507,  0.355495, -0.275172,
           0.027480, -0.011604, -0.089783,  0.041121 },
        // [2][9]
        {  0.047837, -0.253452, -0.229975, -0.193386, -0.037101,  0.139745,
           1.819734, -0.157168,  0.019491, -0.229975,  0.393373, -0.279742,
           0.018133,  0.004358, -0.092974,  0.031101 }
    }, { // [3]
        // [3][0]
        { -0.183163, -0.266985, -0.183163,  0.043693, -0.065196,  1.653084,
          -0.065196,  0.007535, -0.235574,  0.651196, -0.235574,  0.032411,
          -0.010222, -0.149528, -0.010222,  0.016902 },
        // [3][1]
        { -0.151962, -0.275321, -0.219852,  0.048915, -0.180783,  1.666033,
           0.089594, -0.031369, -0.275321,  0.650286, -0.180783,  0.008558,
           0.008558, -0.151962, -0.031369,  0.026777 },
        // [3][2]
        { -0.114726, -0.281773, -0.248865,  0.047468, -0.254647,  1.592521,
           0.288363, -0.082679, -0.285522,  0.603626, -0.094397, -0.028258,
           0.025124, -0.148955, -0.053683,  0.036405 },
        // [3][3]
        { -0.075566, -0.286304, -0.269214,  0.037985, -0.286304,  1.445920,
           0.518423, -0.141091, -0.269214,  0.518423,  0.016932, -0.075566,
           0.037985, -0.141091, -0.075566,  0.044250 },
        // [3][4]
        { -0.038261, -0.288490, -0.281539,  0.020100, -0.281539,  1.245955,
           0.765031, -0.199434, -0.232773,  0.405674,  0.144116, -0.129173,
           0.046327, -0.129173, -0.095881,  0.049061 },
        // [3][5]
        { -0.005713, -0.287386, -0.287386, -0.005713, -0.249337,  1.012927,
           1.012927, -0.249337, -0.183693,  0.277180,  0.277180, -0.183693,
           0.049942, -0.113919, -0.113919,  0.049942 },
        // [3][6]
        {  0.020100, -0.281539, -0.288490, -0.038261, -0.199434,  0.765030,
           1.245955, -0.281539, -0.129173,  0.144116,  0.405674, -0.232773,
           0.049061, -0.095881, -0.129173,  0.046327 },
        // [3][7]
        {  0.037985, -0.269214, -0.286304, -0.075566, -0.141091,  0.518423,
           1.445920, -0.286304, -0.075566,  0.016932,  0.518423, -0.269214,
           0.044250, -0.075566, -0.141091,  0.037985 },
        // [3][8]
        {  0.047468, -0.248865, -0.281773, -0.114726, -0.082679,  0.288363,
           1.592520, -0.254647, -0.028257, -0.094397,  0.603625, -0.285522,
           0.036405, -0.053683, -0.148955,  0.025124 },
        // [3][9]
        {  0.048915, -0.219852, -0.275321, -0.151962, -0.031369,  0.089594,
           1.666032, -0.180782,  0.008558, -0.180783,  0.650286, -0.275321,
           0.026777, -0.031369, -0.151962,  0.008558 }
    }, { // [4]
        // [4][0]
        { -0.138411, -0.273987, -0.138411,  0.038828, -0.108582,  1.442786,
          -0.108582,  0.012944, -0.199271,  0.922267, -0.199271,  0.025923,
          -0.047797, -0.205346, -0.047797,  0.024709 },
        // [4][1]
        { -0.106894, -0.280902, -0.175061,  0.046823, -0.208111,  1.451089,
           0.025207, -0.023361, -0.259376,  0.923877, -0.117273, -0.002760,
          -0.023361, -0.209184, -0.075754,  0.035041 },
        // [4][2]
        { -0.072318, -0.283278, -0.206984,  0.049850, -0.267914,  1.381309,
           0.200462, -0.072318, -0.286025,  0.868400,  0.000000, -0.044463,
           0.000000, -0.206984, -0.103448,  0.043712 },
        // [4][3]
        { -0.038261, -0.281539, -0.232773,  0.046327, -0.288490,  1.245955,
           0.405674, -0.129173, -0.281539,  0.765031,  0.144116, -0.095881,
           0.020100, -0.199434, -0.129173,  0.049061 },
        // [4][4]
        { -0.007702, -0.275978, -0.252355,  0.035491, -0.275978,  1.063146,
           0.627325, -0.187372, -0.252355,  0.627325,  0.304388, -0.151969,
           0.035491, -0.187372, -0.151969,  0.049886 },
        // [4][5]
        {  0.017293, -0.266457, -0.266457,  0.017293, -0.239189,  0.851408,
           0.851408, -0.239189, -0.206515,  0.469434,  0.469434, -0.206515,
           0.045464, -0.171437, -0.171437,  0.045464 },
        // [4][6]
        {  0.035491, -0.252355, -0.275978, -0.007702, -0.187372,  0.627325,
           1.063146, -0.275978, -0.151969,  0.304388,  0.627325, -0.252355,
           0.049886, -0.151969, -0.187372,  0.035491 },
        // [4][7]
        {  0.046327, -0.232772, -0.281539, -0.038261, -0.129173,  0.405674,
           1.245955, -0.288490, -0.095881,  0.144116,  0.765031, -0.281539,
           0.049061, -0.129173, -0.199434,  0.020100 },
        // [4][8]
        {  0.049850, -0.206984, -0.283278, -0.072318, -0.072318,  0.200462,
           1.381310, -0.267914, -0.044463,  0.000000,  0.868400, -0.286025,
           0.043712, -0.103448, -0.206984,  0.000000 },
        // [4][9]
        {  0.046823, -0.175061, -0.280902, -0.106894, -0.023361,  0.025207,
           1.451089, -0.208111, -0.002760, -0.117273,  0.923877, -0.259376,
           0.035041, -0.075754, -0.209184, -0.023361 }
    }, { // [5]
        // [5][0]
        { -0.091757, -0.250136, -0.091757,  0.032272, -0.155112,  1.192366,
          -0.155112,  0.019236, -0.155112,  1.192366, -0.155112,  0.019236,
          -0.091757, -0.250136, -0.091757,  0.032272 },
        // [5][1]
        { -0.062781, -0.255485, -0.125189,  0.041987, -0.235621,  1.196923,
          -0.046205, -0.013627, -0.235621,  1.196923, -0.046205, -0.013627,
          -0.062781, -0.255485, -0.125189,  0.041987 },
        // [5][2]
        { -0.033132, -0.255000, -0.156383,  0.048436, -0.279226,  1.133429,
           0.101247, -0.059371, -0.279226,  1.133429,  0.101247, -0.059371,
          -0.033132, -0.255000, -0.156383,  0.048436 },
        // [5][3]
        { -0.005713, -0.249337, -0.183693,  0.049942, -0.287386,  1.012927,
           0.277180, -0.113919, -0.287386,  1.012927,  0.277180, -0.113919,
          -0.005713, -0.249337, -0.183693,  0.049942 },
        // [5][4]
        {  0.017293, -0.239189, -0.206515,  0.045464, -0.266457,  0.851408,
           0.469434, -0.171437, -0.266457,  0.851408,  0.469434, -0.171437,
           0.017293, -0.239189, -0.206515,  0.045464 },
        // [5][5]
        {  0.034558, -0.224927, -0.224927,  0.034558, -0.224927,  0.665297,
           0.665297, -0.224927, -0.224927,  0.665297,  0.665297, -0.224927,
           0.034558, -0.224927, -0.224927,  0.034558 },
        // [5][6]
        {  0.045464, -0.206515, -0.239189,  0.017293, -0.171437,  0.469434,
           0.851407, -0.266457, -0.171437,  0.469434,  0.851407, -0.266457,
           0.045464, -0.206515, -0.239189,  0.017293 },
        // [5][7]
        {  0.049942, -0.183693, -0.249337, -0.005713, -0.113919,  0.277180,
           1.012927, -0.287386, -0.113919,  0.277180,  1.012927, -0.287386,
           0.049942, -0.183693, -0.249337, -0.005713 },
        // [5][8]
        {  0.048436, -0.156383, -0.255000, -0.033132, -0.059371,  0.101247,
           1.133429, -0.279226, -0.059371,  0.101247,  1.133429, -0.279226,
           0.048436, -0.156383, -0.255000, -0.033132 },
        // [5][9]
        {  0.041987, -0.125189, -0.255485, -0.062781, -0.013627, -0.046205,
           1.196923, -0.235621, -0.013627, -0.046205,  1.196923, -0.235621,
           0.041987, -0.125189, -0.255485, -0.062781 }
    }, { // [6]
        // [6][0]
        { -0.047797, -0.205346, -0.047797,  0.024709, -0.199271,  0.922267,
          -0.199271,  0.025923, -0.108582,  1.442786, -0.108582,  0.012944,
          -0.138411, -0.273987, -0.138411,  0.038828 },
        // [6][1]
        { -0.023361, -0.209184, -0.075754,  0.035041, -0.259376,  0.923877,
          -0.117272, -0.002760, -0.208111,  1.451089,  0.025207, -0.023361,
          -0.106894, -0.280902, -0.175061,  0.046823 },
        // [6][2]
        {  0.000000, -0.206984, -0.103448,  0.043712, -0.286025,  0.868400,
           0.000000, -0.044463, -0.267914,  1.381309,  0.200462, -0.072318,
          -0.072318, -0.283278, -0.206984,  0.049850 },
        // [6][3]
        {  0.020100, -0.199434, -0.129173,  0.049061, -0.281539,  0.765030,
           0.144116, -0.095881, -0.288490,  1.245955,  0.405674, -0.129173,
          -0.038261, -0.281539, -0.232773,  0.046327 },
        // [6][4]
        {  0.035491, -0.187372, -0.151969,  0.049886, -0.252355,  0.627325,
           0.304388, -0.151969, -0.275978,  1.063146,  0.627325, -0.187372,
          -0.007702, -0.275978, -0.252355,  0.035491 },
        // [6][5]
        {  0.045464, -0.171437, -0.171437,  0.045464, -0.206515,  0.469434,
           0.469434, -0.206515, -0.239189,  0.851407,  0.851407, -0.239189,
           0.017293, -0.266457, -0.266457,  0.017293 },
        // [6][6]
        {  0.049886, -0.151969, -0.187372,  0.035491, -0.151969,  0.304388,
           0.627325, -0.252355, -0.187372,  0.627325,  1.063146, -0.275978,
           0.035491, -0.252355, -0.275978, -0.007702 },
        // [6][7]
        {  0.049061, -0.129173, -0.199434,  0.020100, -0.095881,  0.144115,
           0.765030, -0.281539, -0.129173,  0.405674,  1.245955, -0.288490,
           0.046327, -0.232773, -0.281539, -0.038261 },
        // [6][8]
        {  0.043712, -0.103448, -0.206984,  0.000000, -0.044463,  0.000000,
           0.868400, -0.286025, -0.072318,  0.200462,  1.381310, -0.267914,
           0.049850, -0.206984, -0.283278, -0.072318 },
        // [6][9]
        {  0.035041, -0.075754, -0.209184, -0.023361, -0.002760, -0.117273,
           0.923877, -0.259376, -0.023361,  0.025207,  1.451089, -0.208111,
           0.046823, -0.175061, -0.280902, -0.106894 }
    }, { // [7]
        // [7][0]
        { -0.010222, -0.149528, -0.010222,  0.016902, -0.235574,  0.651196,
          -0.235574,  0.032411, -0.065196,  1.653085, -0.065196,  0.007535,
          -0.183163, -0.266985, -0.183163,  0.043693 },
        // [7][1]
        {  0.008558, -0.151962, -0.031369,  0.026777, -0.275321,  0.650285,
          -0.180783,  0.008558, -0.180783,  1.666033,  0.089595, -0.031369,
          -0.151962, -0.275321, -0.219852,  0.048915,},
        // [7][2]
        {  0.025124, -0.148955, -0.053683,  0.036405, -0.285522,  0.603625,
          -0.094397, -0.028258, -0.254647,  1.592521,  0.288363, -0.082679,
          -0.114726, -0.281773, -0.248865,  0.047468 },
        // [7][3]
        {  0.037985, -0.141091, -0.075566,  0.044250, -0.269214,  0.518423,
           0.016932, -0.075566, -0.286304,  1.445920,  0.518423, -0.141091,
          -0.075566, -0.286304, -0.269214,  0.037985 },
        // [7][4]
        {  0.046327, -0.129173, -0.095881,  0.049061, -0.232772,  0.405674,
           0.144116, -0.129173, -0.281539,  1.245955,  0.765031, -0.199434,
          -0.038261, -0.288490, -0.281539,  0.020100 },
        // [7][5]
        {  0.049942, -0.113919, -0.113919,  0.049942, -0.183693,  0.277180,
           0.277180, -0.183693, -0.249337,  1.012927,  1.012927, -0.249337,
          -0.005713, -0.287386, -0.287386, -0.005713 },
        // [7][6]
        {  0.049061, -0.095881, -0.129173,  0.046327, -0.129173,  0.144115,
           0.405674, -0.232773, -0.199434,  0.765030,  1.245955, -0.281539,
           0.020100, -0.281539, -0.288490, -0.038261 },
        // [7][7]
        {  0.044250, -0.075566, -0.141091,  0.037985, -0.075566,  0.016932,
           0.518423, -0.269214, -0.141091,  0.518423,  1.445920, -0.286304,
           0.037985, -0.269214, -0.286304, -0.075566 },
        // [7][8]
        {  0.036405, -0.053683, -0.148955,  0.025124, -0.028257, -0.094397,
           0.603625, -0.285522, -0.082679,  0.288363,  1.592520, -0.254647,
           0.047468, -0.248865, -0.281773, -0.114726 },
        // [7][9]
        {  0.026777, -0.031369, -0.151962,  0.008558,  0.008558, -0.180783,
           0.650286, -0.275321, -0.031369,  0.089594,  1.666033, -0.180782,
           0.048915, -0.219852, -0.275321, -0.151962 }
    }, { // [8]
        // [8][0]
        {  0.018282, -0.091830,  0.018282,  0.009671, -0.259005,  0.396702,
          -0.259005,  0.038003, -0.030128,  1.801697, -0.030128,  0.003405,
          -0.220745, -0.220755, -0.220745,  0.046299 },
        // [8][1]
        {  0.031101, -0.092974,  0.004358,  0.018133, -0.279742,  0.393373,
          -0.229975,  0.019491, -0.157168,  1.819735,  0.139746, -0.037101,
          -0.193387, -0.229975, -0.253452,  0.047837 },
        // [8][2]
        {  0.041121, -0.089783, -0.011604,  0.027480, -0.275172,  0.355494,
          -0.173507, -0.011604, -0.241512,  1.745518,  0.355495, -0.089783,
          -0.156579, -0.241512, -0.275172,  0.041121 },
        // [8][3]
        {  0.047468, -0.082679, -0.028257,  0.036405, -0.248865,  0.288363,
          -0.094397, -0.053683, -0.281773,  1.592520,  0.603625, -0.148955,
          -0.114726, -0.254647, -0.285522,  0.025124 },
        // [8][4]
        {  0.049850, -0.072318, -0.044463,  0.043712, -0.206984,  0.200462,
           0.000000, -0.103448, -0.283278,  1.381310,  0.868400, -0.206984,
          -0.072318, -0.267914, -0.286025,  0.000000 },
        // [8][5]
        {  0.048436, -0.059371, -0.059371,  0.048436, -0.156383,  0.101247,
           0.101247, -0.156383, -0.255000,  1.133429,  1.133429, -0.255000,
          -0.033132, -0.279226, -0.279226, -0.033132 },
        // [8][6]
        {  0.043712, -0.044463, -0.072318,  0.049850, -0.103448,  0.000000,
           0.200462, -0.206984, -0.206984,  0.868400,  1.381310, -0.283278,
          -0.000000, -0.286025, -0.267914, -0.072318 },
        // [8][7]
        {  0.036405, -0.028257, -0.082679,  0.047468, -0.053683, -0.094397,
           0.288363, -0.248865, -0.148955,  0.603625,  1.592520, -0.281773,
           0.025124, -0.285522, -0.254647, -0.114726 },
        // [8][8]
        {  0.027480, -0.011604, -0.089783,  0.041121, -0.011604, -0.173507,
           0.355494, -0.275172, -0.089783,  0.355494,  1.745519, -0.241512,
           0.041121, -0.275172, -0.241512, -0.156579 },
        // [8][9]
        {  0.018133,  0.004358, -0.092974,  0.031101,  0.019491, -0.229975,
           0.393373, -0.279742, -0.037101,  0.139745,  1.819735, -0.157168,
           0.047837, -0.253452, -0.229975, -0.193387 }
    }, { // [9]
        // [9][0]
        {  0.036235, -0.040077,  0.036235,  0.003820, -0.265837,  0.175148,
          -0.265837,  0.041959, -0.007606,  1.869223, -0.007606,  0.000848,
          -0.245915, -0.130966, -0.245915,  0.046293 },
        // [9][1]
        {  0.043489, -0.040090,  0.029049,  0.010148, -0.270076,  0.169479,
          -0.259318,  0.029049, -0.140049,  1.891722,  0.169479, -0.040090,
          -0.226157, -0.140049, -0.270076,  0.043489 },
        // [9][2]
        {  0.047837, -0.037101,  0.019491,  0.018133, -0.253452,  0.139745,
          -0.229975,  0.004358, -0.229975,  1.819734,  0.393373, -0.092974,
          -0.193386, -0.157168, -0.279742,  0.031101 },
        // [9][3]
        {  0.048915, -0.031369,  0.008558,  0.026777, -0.219852,  0.089594,
          -0.180783, -0.031369, -0.275321,  1.666032,  0.650286, -0.151962,
          -0.151962, -0.180782, -0.275321,  0.008558 },
        // [9][4]
        {  0.046823, -0.023361, -0.002760,  0.035041, -0.175061,  0.025207,
          -0.117273, -0.075754, -0.280902,  1.451089,  0.923877, -0.209184,
          -0.106894, -0.208111, -0.259376, -0.023361 },
        // [9][5]
        {  0.041987, -0.013627, -0.013627,  0.041987, -0.125189, -0.046205,
          -0.046205, -0.125189, -0.255485,  1.196923,  1.196923, -0.255485,
          -0.062781, -0.235621, -0.235621, -0.062781 },
        // [9][6]
        {  0.035041, -0.002760, -0.023361,  0.046823, -0.075754, -0.117273,
           0.025207, -0.175061, -0.209184,  0.923877,  1.451089, -0.280902,
          -0.023361, -0.259376, -0.208111, -0.106894 },
        // [9][7]
        {  0.026777,  0.008558, -0.031369,  0.048915, -0.031369, -0.180783,
           0.089594, -0.219852, -0.151962,  0.650286,  1.666033, -0.275321,
           0.008558, -0.275321, -0.180782, -0.151962 },
        // [9][8]
        {  0.018133,  0.019491, -0.037101,  0.047837,  0.004358, -0.229975,
           0.139745, -0.253452, -0.092974,  0.393373,  1.819735, -0.229975,
           0.031101, -0.279742, -0.157168, -0.193387 },
        // [9][9]
        {  0.010148,  0.029049, -0.040090,  0.043489,  0.029049, -0.259318,
           0.169479, -0.270076, -0.040090,  0.169479,  1.891723, -0.140049,
           0.043489, -0.270076, -0.140049, -0.226157 }
    }
};

// Device 子程序：_fanczosInterpoDev（Fanczos 插值）
static __device__ unsigned char _fanczosInterpoDev(const ImageCuda &inimg,
                                                   float x, float y)
{
    // 为了减少算法的执行时间，这里没有对 inimg 的合法性进行检查。

    // 如果给定的坐标不再图像的返回内，返回 0 值。
    if (x < 0.0f || y < 0.0f ||
        x >= inimg.imgMeta.width || y >= inimg.imgMeta.height)
        return 0;

    // 分离给定坐标的正数部分和小数部分，整数部分存放入 intx 和 inty，小数部分
    // 存放入 dx 和 dy。这里小数部分只保留了 1 位小数，并用整数的方式保存。
    int intx, inty, dx, dy;
    intx = (int)x;
    inty = (int)y;
    dx = (int)((x - intx) * 10.0f);
    dy = (int)((y - inty) * 10.0f);

    // 为了代码的简洁，这里将一些常用的参数的分量使用了别的名称替代，希望 CUDA
    // 足够聪明，这些用来替代较长名称的变量不会带来额外的性能负担。
    unsigned char *inptr = inimg.imgMeta.imgData;
    size_t pitch = inimg.pitchBytes;
    const float *iplparam = _fanczosCoeffDev[dy][dx];

    // 由于图像边缘的点存在越界访存的情况，因此对于边缘点采取临近点插值的方法。
    // 虽然，临近点插值是各种插值算法中最弱的，但考虑到河边老师提供的参考代码就
    // 是如此，故委托方未作改变。
    if (intx < 3 || inty < 3 ||
        intx >= inimg.imgMeta.width - 3 || inty >= inimg.imgMeta.height - 3)
        return inptr[inty * pitch + intx];

    // 根据当前点周围的 4×4 临近点计算出该点的插值。这个插值根据 Fanzcos 系数
    // 做加权平均数。同样，这里我们也希望 CUDA 足够聪明，这些 += 不要带来额外的
    // 性能负担。这里，我们考虑到计算的准确性与灵活性，插值暂用浮点型数据表示，
    // 下边的步骤中，我们会将它安全的转换成 unsigned char。
    float tmpipl = 0.0f;
    tmpipl += iplparam[ 0] * inptr[(inty - 1) * pitch + (intx - 1)];
    tmpipl += iplparam[ 1] * inptr[(inty - 1) * pitch + (intx    )];
    tmpipl += iplparam[ 2] * inptr[(inty - 1) * pitch + (intx + 1)];
    tmpipl += iplparam[ 3] * inptr[(inty - 1) * pitch + (intx + 2)];
    tmpipl += iplparam[ 4] * inptr[(inty    ) * pitch + (intx - 1)];
    tmpipl += iplparam[ 5] * inptr[(inty    ) * pitch + (intx    )];
    tmpipl += iplparam[ 6] * inptr[(inty    ) * pitch + (intx + 1)];
    tmpipl += iplparam[ 7] * inptr[(inty    ) * pitch + (intx + 2)];
    tmpipl += iplparam[ 8] * inptr[(inty + 1) * pitch + (intx - 1)];
    tmpipl += iplparam[ 9] * inptr[(inty + 1) * pitch + (intx    )];
    tmpipl += iplparam[10] * inptr[(inty + 1) * pitch + (intx + 1)];
    tmpipl += iplparam[11] * inptr[(inty + 1) * pitch + (intx + 2)];
    tmpipl += iplparam[12] * inptr[(inty + 2) * pitch + (intx - 1)];
    tmpipl += iplparam[13] * inptr[(inty + 2) * pitch + (intx    )];
    tmpipl += iplparam[14] * inptr[(inty + 2) * pitch + (intx + 1)];
    tmpipl += iplparam[15] * inptr[(inty + 2) * pitch + (intx + 2)];

    // 将浮点型的临时的插值值，转换为 unsigned char 型。注意，我们没有直接采用
    // 类型强转，就是因为防止数据越界引起的不确定结果。
    if (tmpipl > 255.0f)     // 对于高于 unsigned char 限度 255 的值，将其直接
        return 255;          // 削平至 255。
    else if (tmpipl < 0.0f)  // 对于低于 unsigned char 限度 0 的值，将其直接修
        return 0;            // 正至 0。
    else
        return (unsigned char)tmpipl;
}

#endif

